﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ERF;
using ERF.Physics;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using FirstPerson.States;
using Microsoft.Xna.Framework.Audio;


namespace FirstPerson.Objects.Pickups
{
    abstract class Pickable : ModelGameObject
    {
        protected float mass = 50f;
        protected Body body;
        protected event EventHandler<PickedEventArgs> Picked;
        protected float spawnTime, time;
        protected SoundHandler sound;
        protected SoundEffect mySound;

        public Pickable(Game game, string modelString)
            : base((ERFGame)game)
        {
            this.ObjectModel = game.Content.Load<Model>(modelString);
            SetEffect();

            sound = ((ERFGame)game).SoundHandler;
            CreateBody();
        }

        public Body PhysicsBody
        {
            get { return this.body; }
        }

        protected void Play3DSound(SoundEffect soundEffect)
        {

            SoundEffectInstance soundInstance = soundEffect.CreateInstance();
            soundInstance.Volume = 0.7f;
            sound.Play3DSound(soundInstance, this, (base.CurrentGame.PlayerHandler as FirstPerson.PlayerHandler).HumanPlayer);

        }

        public override Vector3 Scale
        {
            get
            {
                return base.Scale;
            }
            set
            {
                base.Scale = value;
                this.CreateBody();
            }
        }

        protected virtual void CreateBody()
        {
            //BoundingBox box = new BoundingBox(
            //    new Vector3(-0.5f, -1f, -0.5f),
            //    new Vector3(0.5f, 1f, 0.5f));

            BoundingBox box = (BoundingBox)base.ObjectModel.Tag;
            box.Min *= base.scale;
            box.Max *= base.scale;

            this.body = new Body(Vector3.Zero, box, 0, 0, false, this.mass, this);
            this.body.BodyChanged += new EventHandler(body_BodyChanged);
        }

        protected virtual void body_BodyChanged(object sender, EventArgs e)
        {
            Vector3 feetPosition = this.body.position;
            //feetPosition.Y -= this.body.boundingBox.Max.Y;
            this.position = feetPosition;
        }


        public override void Update(GameTime gameTime, ref Matrix world)
        {
            this.rotation.Y+=0.03f;
            this.time += (float)gameTime.ElapsedGameTime.TotalSeconds;
            if (this.time > this.spawnTime)
            {
                this.Visible = true;
                this.time = 0;
            }
            base.Update(gameTime, ref world);
        }

        private void SetEffect()
        {
            for (int i = 0; i < this.ObjectModel.Meshes.Count; i++)
            {
                for (int j = 0; j < this.ObjectModel.Meshes[i].MeshParts.Count; j++)
                {
                    BasicShaderEffect effect = new BasicShaderEffect(base.CurrentGame);
                    if (this.ObjectModel.Meshes[i].MeshParts[j].Effect is BasicEffect)
                    {
                        BasicEffect oldEffect = (BasicEffect)this.ObjectModel.Meshes[i].MeshParts[j].Effect;
                        effect.DiffuseColor = oldEffect.DiffuseColor;
                        effect.LightDirection = new Vector3(0, 1, 1);
                        effect.AmbientColor = Color.White.ToVector3();
                        effect.AmbientIntensity = 0.7f;
                        effect.DiffuseIntensity = 1f;
                        effect.SpecularColor = oldEffect.SpecularColor;
                        effect.SpecularIntensity = 1f;
                        effect.SpecularPower = 32f;
                        effect.Texture = oldEffect.Texture;
                        effect.EnableTexture = (effect.Texture != null);
                        effect.EnableLight = true;
                        effect.FogColor = Color.White.ToVector4();
                        effect.FogStart = 10.1f;
                        effect.FogEnd = 10f;
                        effect.FogEnabled = false;
                    }
                    else
                    {
                        BasicShaderEffect oldEffect = (BasicShaderEffect)this.ObjectModel.Meshes[i].MeshParts[j].Effect;
                        effect.DiffuseColor = oldEffect.DiffuseColor;
                        effect.LightDirection = new Vector3(0, 1, 1);
                        effect.AmbientColor = Color.White.ToVector3();
                        effect.AmbientIntensity = 0.7f;
                        effect.DiffuseIntensity = 1f;
                        effect.SpecularColor = oldEffect.SpecularColor;
                        effect.SpecularIntensity = 1f;
                        effect.SpecularPower = 32f;
                        effect.Texture = oldEffect.Texture;
                        effect.EnableTexture = (effect.Texture != null);
                        effect.EnableLight = true;
                        effect.FogColor = Color.White.ToVector4();
                        effect.FogStart = 10.1f;
                        effect.FogEnd = 10f;
                        effect.FogEnabled = false;
                    }

                    base.meshEffects[i][j] = effect;
                }
            }
        }

        public void PickedUp(Player player) {
            if (this.Visible) {
                this.time = 0;
                this.Picked(this, new PickedEventArgs(this, player));
            }
            this.Visible = false;
        }
    }
    class PickedEventArgs : EventArgs
    {
        protected Pickable pickable;
        protected Player player;
        public PickedEventArgs(Pickable pick, Player player) : base() {
            this.pickable = pick;
            this.player = player;
        }
        public Pickable Pickable {
            get { return this.pickable; }
        }
        public Player Player {
            get { return this.player; }
        }
    }
}
